/**
 * UninaDocentiSync - A Java application to synchronize Unina resources
 * Copyright (C) 2011  Fabio Scippacercola (nonplay.programmer@gmail.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * UpdatingDialog.java
 *
 * Created on Oct 22, 2011, 11:30:01 PM
 */

package uninadocentisync.guibeans;

import uninadocentisync.UninaDocentiSyncApp;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.logging.Level;
import javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultTreeModel;
import uninadocenti.framework.Insegnamento;
import uninadocenti.framework.WebDocentiFile;
import uninadocenti.framework.synch.SynchManager;
import uninadocenti.framework.synch.SynchUpdateEvent;
import uninadocenti.framework.synch.SynchingFile;

/**
 *
 * @author user
 */
public class UpdatingDialog extends javax.swing.JDialog {

    /** Creates new form UpdatingDialog */
    public UpdatingDialog(UninaDocentiSyncApp uninaApp, final Insegnamento[] insList) {
        initComponents();
        setLocationRelativeTo(null);
        
        jTree1.putClientProperty("JTree.lineStyle", "Angled");
        jTree1.setComponentPopupMenu(jTreePopUp);
        synchManager1.setSyncApp(uninaApp);

        updateSel = new JMenuItem("Aggiorna selezionati");
        skipSel = new JMenuItem("Tralascia i selezionati");
        jTreePopUp.add(updateSel);
        jTreePopUp.add(skipSel);
        updateSel.setEnabled(false);
        skipSel.setEnabled(false);

        updateSel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                ActionChangeNodePropertiesPerformed(evt, SynchingFile.State.TODOWNLOAD);
            }
        });

        skipSel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                ActionChangeNodePropertiesPerformed(evt, SynchingFile.State.TOSKIP);
            }
        });

        logBuilder = new StringBuilder();
        logBuilder.append("<html><body><font style=\"font-family: sans-serif; font-size: 11pt\">");

        Thread t = new Thread() {
            @Override
            public void run() {
                try {
                synchManager1.createList(insList);
                } catch (IOException e) {
                    // TODO
                    //Appendere al logger!
                }
            }
        };
        t.start();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        synchManager1 = new uninadocenti.framework.synch.SynchManager();
        jTreePopUp = new javax.swing.JPopupMenu();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        jLabel1 = new javax.swing.JLabel();
        jProgressBar1 = new javax.swing.JProgressBar();
        closeButton = new javax.swing.JButton();
        downloadButton = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jEditorPane1 = new javax.swing.JEditorPane();
        jLabel2 = new javax.swing.JLabel();

        synchManager1.addSynchManagerListener(new uninadocenti.framework.synch.SynchManagerListener() {
            public void synchUpdate(uninadocenti.framework.synch.SynchUpdateEvent evt) {
                synchManager1SynchUpdate(evt);
            }
            public void DownloadingTreeChanged(java.util.EventObject evt) {
                synchManager1DownloadingTreeChanged(evt);
            }
            public void FileSyncStateChanged(java.beans.PropertyChangeEvent evt) {
                synchManager1FileSyncStateChanged(evt);
            }
        });

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("UninaDocentiSync");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        jTree1.setCellRenderer(new uninadocentisync.guibeans.UninaTreeNode.UninaTreeCellRender());
        jTree1.setRootVisible(false);
        jScrollPane1.setViewportView(jTree1);

        jLabel1.setText("Aggiornamento in corso...");

        closeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/uninadocentisync/gui/res/System-log-out-2.png"))); // NOI18N
        closeButton.setText("Chiudi");
        closeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeButtonActionPerformed(evt);
            }
        });

        downloadButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/uninadocentisync/gui/res/Document-save.png"))); // NOI18N
        downloadButton.setText("Download");
        downloadButton.setEnabled(false);
        downloadButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                downloadButtonActionPerformed(evt);
            }
        });

        jEditorPane1.setBackground(new java.awt.Color(255, 255, 255));
        jEditorPane1.setContentType("text/html");
        jEditorPane1.setEditable(false);
        jScrollPane2.setViewportView(jEditorPane1);

        jLabel2.setFont(new java.awt.Font("DejaVu Sans", 0, 10)); // NOI18N
        jLabel2.setText("Tasto destro per menù opzioni");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 409, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addComponent(downloadButton, javax.swing.GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(closeButton, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE))
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 409, Short.MAX_VALUE)
                    .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 409, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(closeButton)
                        .addComponent(downloadButton))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 419, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(34, 34, 34)))
                        .addGap(6, 6, 6)
                        .addComponent(jLabel2)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void synchManager1DownloadingTreeChanged(java.util.EventObject evt) {//GEN-FIRST:event_synchManager1DownloadingTreeChanged
        Runnable r = new Runnable() {
            public void run() {
                updateTreeView();
            }
        };

        if (SwingUtilities.isEventDispatchThread()) r.run();
        else SwingUtilities.invokeLater(r);
    }//GEN-LAST:event_synchManager1DownloadingTreeChanged

    private void ActionChangeNodePropertiesPerformed(ActionEvent evt, final SynchingFile.State s) {
        Runnable r = new Runnable() {
            public void run() {
                if (synchManager1.getState() == SynchManager.State.READY)
                {
                    final int[] v = jTree1.getSelectionRows();
                    if (v != null)
                        for (int i = 0; i < v.length; i++)
                            changeFileNodeState(((UninaTreeNode)(jTree1.getPathForRow(v[i]).getLastPathComponent())));

                    jTree1.repaint();
                }

            }

            public void changeFileNodeState(final UninaTreeNode f) {
                f.resAssociated.setDownloadState(s);
                for (int i = 0; i < f.getChildCount(); i++)
                    changeFileNodeState((UninaTreeNode)f.getChildAt(i));
            }
        };

        if (SwingUtilities.isEventDispatchThread()) r.run();
        else SwingUtilities.invokeLater(r);
    }

    private void synchManager1FileSyncStateChanged(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_synchManager1FileSyncStateChanged
        final java.beans.PropertyChangeEvent e = evt;
        Runnable r = new Runnable() {
            public void run() {
                final SynchManager.State s = (SynchManager.State)e.getNewValue();
                downloadButton.setEnabled(s == SynchManager.State.READY);
                updateSel.setEnabled(s == SynchManager.State.READY);
                skipSel.setEnabled(s == SynchManager.State.READY);
                jProgressBar1.setIndeterminate(s == SynchManager.State.ANALYZING);

                switch (s) {
                    case ANALYZING: {
                        jLabel1.setText("Analisi cartelle docenti...");
                        break;
                    }
                    case COMPLETED: {
                        jLabel1.setText("Sincronizzazione completata!");
                        appendText(String.format("<font color=\"#2B8F2B\">Tutte le risorse sono state sincronizzate correttamente!\n<br>File scaricati: %d\nTotale bytes: %d</font>",
                                synchManager1.getFileDownloaded(), synchManager1.getTotalBytesDownloaded()), null);
                        break;
                    }
                    case DOWNLOADING: {
                        jLabel1.setText("Sincronizzazione risorse...");
                        break;
                    }
                    case ERROR: {
                        jLabel1.setText("Si sono verificati degli errori!");
                        break;
                    }
                    case READY: {
                        jLabel1.setText("Pronto per il download!");
                        break;
                    }
                    case INTERRUPTED: {
                        jLabel1.setText("Azione interrotta!");
                        break;
                    }
                    default: {
                        jLabel1.setText("Nessuna operazione in esecuzione");
                        break;
                    }
                }
            }
        };

        if (SwingUtilities.isEventDispatchThread()) r.run();
        else SwingUtilities.invokeLater(r);
    }//GEN-LAST:event_synchManager1FileSyncStateChanged

    private void synchManager1SynchUpdate(uninadocenti.framework.synch.SynchUpdateEvent evt) {//GEN-FIRST:event_synchManager1SynchUpdate
        final uninadocenti.framework.synch.SynchUpdateEvent e = evt;
        Runnable r = new Runnable() {
            public void run() {
                switch (e.eventType) {
                    case FOLDER_VISITED: {
                        appendText(null, new String[] {"Visitando la cartella: ", ((SynchUpdateEvent.FolderVisitedPayload)e.payload).folderName});
                        break;
                    }
                    case LOG_MSG: {
                        final SynchUpdateEvent.LogMessagePayload p = (SynchUpdateEvent.LogMessagePayload)e.payload;
                        final java.util.logging.LogRecord lr = p.lr;
                        if (lr.getLevel() == Level.WARNING || lr.getLevel() == Level.SEVERE)
                            appendText(null, new String[] { "<font color=\"red\">", lr.getLevel().toString(), ": ", lr.getMessage(), "</font>"});
                        else
                            appendText(null, new String[] { lr.getLevel().toString(), ": ", lr.getMessage()});
                        break;
                    }
                    case NODE_UPDATE: {
                        final SynchUpdateEvent.NodeUpdatePayload p = (SynchUpdateEvent.NodeUpdatePayload)e.payload;

                        jTree1.repaint();
                        jProgressBar1.setValue(synchManager1.getFileDownloaded());
                        jProgressBar1.setMaximum(synchManager1.getFileToDownload());
                        if (p.newState == SynchingFile.State.DOWNLOADED)
                            appendText(String.format("%s [%dB]",
                                ((WebDocentiFile)p.f.getResource()).getName(), p.fileSize), null);
                        break;
                    }
                }
            }
        };

        if (SwingUtilities.isEventDispatchThread()) r.run();
        else SwingUtilities.invokeLater(r);
    }//GEN-LAST:event_synchManager1SynchUpdate

    private void downloadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadButtonActionPerformed
        Thread t = new Thread() {
            @Override
            public void run() {
                synchManager1.startDownload();
            }
        };
        t.start();
        downloadButton.setEnabled(false);
    }//GEN-LAST:event_downloadButtonActionPerformed

    private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
        dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
    }//GEN-LAST:event_closeButtonActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        final SynchManager.State s = synchManager1.getState();
        final String mex = (s == SynchManager.State.READY ? "Devi ancora sincronizzare le risorse: sei sicuro di voler uscire?"
                            : "Operazioni in corso: sei sicuro di voler uscire?");

        if ((!(s == SynchManager.State.ANALYZING || s == SynchManager.State.DOWNLOADING || s == SynchManager.State.READY)
                 || JOptionPane.showConfirmDialog(this, mex, "Uscire?", JOptionPane.YES_NO_OPTION)
            == JOptionPane.YES_OPTION))
        {
            setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            synchManager1.interrupt();
        }
        else
        {
             setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        }
    }//GEN-LAST:event_formWindowClosing

    protected void appendText(String s1, String[] sv) {
        if (s1 != null) logBuilder.append(s1);
        if (sv != null) for (int i = 0; i < sv.length; i++) logBuilder.append(sv[i]);
        logBuilder.append("<br>");

        jEditorPane1.setText(logBuilder.toString());
    }

    protected void updateTreeView() {
        final int INITIAL_HASH_MAP_CAPACITY = 1000;

        java.util.HashMap<SynchingFile<WebDocentiFile>, UninaTreeNode> hashTree = new java.util.HashMap<SynchingFile<WebDocentiFile>, UninaTreeNode>(INITIAL_HASH_MAP_CAPACITY);
        UninaTreeNode uninaRoot = mapTree(hashTree, synchManager1.getRoot());
        DefaultTreeModel tm = new DefaultTreeModel(uninaRoot);

        jTree1.setModel(tm);
        for (int i = 0; i < jTree1.getRowCount(); i++) {
            jTree1.expandRow(i);
        }
    }

    protected UninaTreeNode mapTree(java.util.HashMap<SynchingFile<WebDocentiFile>, UninaTreeNode> t, SynchingFile<WebDocentiFile> n)
    {
        final UninaTreeNode tn = new UninaTreeNode(t, n);
        t.put(n, tn);

        if (n.hasChildren())
            for (SynchingFile<WebDocentiFile> c : n.getChildren())
                mapTree(t, c);
        return tn;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton closeButton;
    private javax.swing.JButton downloadButton;
    private javax.swing.JEditorPane jEditorPane1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTree jTree1;
    private javax.swing.JPopupMenu jTreePopUp;
    private uninadocenti.framework.synch.SynchManager synchManager1;
    // End of variables declaration//GEN-END:variables
    private JMenuItem updateSel;
    private JMenuItem skipSel;
    private StringBuilder logBuilder;
}
